/*--------------------------------------------------------------------------
 *
 * 	You may freely copy, distribute, and reuse the code in this example.
 * 	SHL Systemhouse disclaims any warranty of any kind, expressed or  
 *	implied, as to its fitness for any particular use.
 *
 *
 *	Controller
 *
 *	Category Of:	EOFDelegate
 *
 *	Conforms To:	None
 *
 *	Declared In:	EOFDelegateControllerCategory.h
 *
 *
 *------------------------------------------------------------------------*/
#import "EOFDelegateControllerCategory.h"




@implementation EOFDelegate (Controller)

/*--------------------------------------------------------------------------
 *	EOController Delegate Methods
 *
 *  Note that the insert, delete, and update operations are buffered until an
 *  -saveToDataSource message is sent to the controller.  The delegate receives
 *  delegate messages for these operations as the insert, delete, and update
 *  operations are sent to the controller.  The delegate receives different
 *  delegate messages when the buffered operations are actually sent on to the
 *  data source.
 *
 *  typedef enum {
 *    EONoDataSourceFailure = 0,
 *    EOContinueDataSourceFailureResponse,
 *    EORollbackDataSourceFailureResponse
 *  } EODataSourceFailureResponse;
 *
 *  These return values allow a controller's delegate to determine what
 *  action should be taken on a failure.  EONoDataSourceFailure means there
 *  was no failure; EOContinuteDataSourceFailureResponse means that the
 *  failure should be ignored and the operation should continue;
 *  EORollbackDataSourceFailureResponse means that the controller should
 *  roll back the data source.  EORollbackDataSourceFailureResponse is only
 *  useful if the data source conforms to the EORollbackDataSource
 *  protocol.
 *
 *------------------------------------------------------------------------*/
- (void)controllerDidChangeSelection:(EOController *)controller
{
    // Sent when the selection changes.
	
	[[NXApp delegate] announce:controller selector:_cmd];
}

    
- (BOOL)controllerWillFetch:(EOController *)controller
{
    // Informs the delegate that the controller is about to fetch.  If the
    // delegate returns no the fetch fails; if the delegate returns YES
    // the fetch proceeds.
	
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller selector:_cmd];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller didFetchObjects: (NSArray *)objects
{
    // Informs the delegate that the controller has fetched object.
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject:objects]];
}


- (BOOL)controller:(EOController *)controller 
	willInsertObject:object 
	atIndex: (unsigned)newIndex
{
    // If the delegate returns NO object is released and not inserted.
	
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject:object]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller didInsertObject:object
{
    // Informs the delegate that the controller has inserted object.
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject:object]];
}


- (BOOL)controller:(EOController *)controller willDeleteObject:object
{
    // If the delegate returns NO object is not deleted.
	
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject:object]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller didDeleteObject:object
{
    // Informs the delegate that the controller has deleted object.
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject:object]];
}


- (NSDictionary *)controller:(EOController *)controller 
	willSaveEdits: (NSDictionary *)edits 
	toObject:object
{	
    // Invoked by -saveObjects for each object before
    // -takeValuesFromDictionary: is sent to the object.  If the delegate
    // responds nil -takeValuesFromDictionary: is not sent and the controller
    // aborts -saveToObjects.  The edits will be ignored and the associations
    // will not be notified of any change.  If the delegate returns a
    // dictionary that dictionary will be sent to the object.  This method is
    // useful for doing validation prior to data actually being sent to the
    // object and will also prevent the UI from refreshing.
	
	id	result = edits;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: edits, object, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = nil;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = edits;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller didSaveToObject:object
{
    // Informs the delegate that the controller has saved object.
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject:object]];
}


/*--------------------------------------------------------------------------
 *	NOTE
 *	
 *	The following two methods have been commented out to allow natural
 *	processing of associated events.  See comments below for these methods.
 *
 
- (BOOL)controllerWillDiscardEdits:(EOController *)controller
{
    // Sent during the -fetch method before the fetch begins if there are any
    // operations that haven't been saved to the objects.  Also sent when a
    // selection is about to change, causing a detail controller to flush its
    // caches.  The operation is aborted if this method returns NO.  The
    // delegate should send -saveToObjects if it wants to preserve the
    // changes.  If the delegate doesn't implement this method the controller
    // opens an alert panel warning the user that edits may be lost.
	
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller selector:_cmd];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (BOOL)controllerWillDiscardOperations:(EOController *)controller
{
    // Sent during the -fetch method before the fetch begins if there are any
    // operations that haven't been saved to the data source.  Also sent
    // when a selection is about to change, causing a detail controller to
    // flush its caches.  The fetch is aborted if this method returns NO.
    // The delegate should invoke -saveToDataSource if it wants to preserve the
    // changes.  If the delegate doesn't implement this method the controller
    // opens an alert panel warning the user that updates may be lost.
	
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller selector:_cmd];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}
 *------------------------------------------------------------------------*/



- (BOOL)controllerWillSaveToDataSource:(EOController *)controller
{
    // These delegate messages are sent as the data source is notified of
    // changes to data-bearing objects.  If the savesToDataSourceAutomatically
    // flag is turned off and -saveToDataSource is invoked then the delegate
    // is notified of each buffered operation.
	
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller selector:_cmd];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (void)controllerDidSaveToDataSource:(EOController *)controller
{
    // These delegate messages are sent as the data source is notified of
    // changes to data-bearing objects.  If the savesToDataSourceAutomatically
    // flag is turned off and -saveToDataSource is invoked then the delegate
    // is notified of each buffered operation.

	[[NXApp delegate] announce:controller selector:_cmd];
}


- (EODataSourceOperationDelegateResponse)controller:(EOController *)controller
    willInsertObject:object
    inDataSource:dataSource
{
	int	result = EOPerformDataSourceOperation;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = EODiscardDataSourceOperation;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = EOPerformDataSourceOperation;
				break;
			}
		}
	
	return result;
}


- (EODataSourceFailureResponse)controller:(EOController *)controller
    failedToInsertObject:object
    inDataSource:dataSource
{
	int	result = EONoDataSourceFailure;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "No Failure", "Continue", "Rollback", sel_getName(_cmd)))
			{
			case NX_ALERTOTHER:
				result = EORollbackDataSourceFailureResponse;
				break;
			case NX_ALERTALTERNATE:
				result = EOContinueDataSourceFailureResponse;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = EONoDataSourceFailure;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller
    didInsertObject:object
    inDataSource:dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
}


- (EODataSourceOperationDelegateResponse)controller:(EOController *)controller
    willDeleteObject:object
    inDataSource:dataSource
{
	int	result = EOPerformDataSourceOperation;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = EODiscardDataSourceOperation;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = EOPerformDataSourceOperation;
				break;
			}
		}
	
	return result;
}


- (EODataSourceFailureResponse)controller:(EOController *)controller
    failedToDeleteObject:object
    inDataSource:dataSource
{
	int	result = EONoDataSourceFailure;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "No Failure", "Continue", "Rollback", sel_getName(_cmd)))
			{
			case NX_ALERTOTHER:
				result = EORollbackDataSourceFailureResponse;
				break;
			case NX_ALERTALTERNATE:
				result = EOContinueDataSourceFailureResponse;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = EONoDataSourceFailure;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller
    didDeleteObject:object
    inDataSource:dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
}


- (EODataSourceOperationDelegateResponse)controller:(EOController *)controller
    willUpdateObject:object
    inDataSource:dataSource
{
	int	result = EOPerformDataSourceOperation;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = EODiscardDataSourceOperation;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = EOPerformDataSourceOperation;
				break;
			}
		}
	
	return result;
}


- (EODataSourceFailureResponse)controller:(EOController *)controller
    failedToUpdateObject:object
    inDataSource:dataSource;
{
	int	result = EONoDataSourceFailure;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "No Failure", "Continue", "Rollback", sel_getName(_cmd)))
			{
			case NX_ALERTOTHER:
				result = EORollbackDataSourceFailureResponse;
				break;
			case NX_ALERTALTERNATE:
				result = EOContinueDataSourceFailureResponse;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = EONoDataSourceFailure;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller
    didUpdateObject:object
    inDataSource:dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: object, dataSource, nil]];
}


- (void)controller:(EOController *)controller 
	willRollbackDataSource:(id <EODataSources>)dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject: dataSource]];
}


- (void)controller:(EOController *)controller 
	didRollbackDataSource:(id <EODataSources>)dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject: dataSource]];
}


- (BOOL)controllerWillUndo:(EOController *)controller
{
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller selector:_cmd];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (void)controllerDidUndo:(EOController *)controller
{
	[[NXApp delegate] announce:controller selector:_cmd];
	
}


- (void)controller:(EOController *)controller 
	didChangeDataSource: (id <EODataSources>)dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject: dataSource]];
}


- (void)controller:(EOController *)controller 
	association: (EOAssociation *)association 
	didEditObject: anObject 
	key: (NSString *)key 
	value: aValue
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObjects: 
			association, anObject, key, aValue, nil]];
}


- (BOOL)controller:(EOController *)controller willUndoObject:anObject
{
	BOOL	result = YES;
	
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject: anObject]];
	
	if ([[NXApp delegate] wantsAlertPanels] == YES)
		{
		switch (NXRunAlertPanel ("EOController", 
			"%s", "YES", "NO", NULL, sel_getName(_cmd)))
			{
			case NX_ALERTALTERNATE:
				result = NO;
				break;
			case NX_ALERTDEFAULT:
			default:
				result = YES;
				break;
			}
		}
	
	return result;
}


- (void)controller:(EOController *)controller didUndoObject:anObject
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject: anObject]];
}

// This delegate method can be implemented to respond when the controller is 
// unable to create an object for a data source. If the delegate does not 
// implement this method, the controller will put up a panel to alert the user
// of the error. Otherwise, the delegate is responsible for notifying the user. 
- (void) controller:(EOController *)controller
    createObjectFailedForDataSource:dataSource
{
	[[NXApp delegate] announce:controller 
		selector:_cmd 
		with:[NSArray arrayWithObject: dataSource]];
}

@end
